module dungeon.item_group;

import std.conv;

import derelict.opengl.gl;

import nade.random;
import nade.ast;
import nade.loader;
import nade.vector;

import dungeon.game;
import dungeon.map;
import dungeon.item;


class ItemQuantity {
	string		name;
	uint		quantityMin = 1, quantityMax = 1;
	int			depthMin = 1, depthMax = int.max, chance = 100;
}

class ItemGroup {
	this(Game game)
	{
		_game = game;
	}

	ItemObject drop(Map map, const Vector2i coord)
	{
		auto item = this.getRandomItem(map.depth);
		return new ItemObject(map, coord, map.game.getItem(item.name), random(item.quantityMin, item.quantityMax+1));
	}

	ItemQuantity getRandomItem(int depth)
	{
		ItemQuantity[] possibles;
		int chanceTotal = 0;

		foreach(item; _items)
		{
			if(depth >= item.depthMin  &&  depth <= item.depthMax)
			{
				possibles ~= item;
				chanceTotal += item.chance;
			}
		}

		if(chanceTotal == 0) assert(false);

		int r = random(0, chanceTotal);
		foreach(item; possibles)
		{
			r -= item.chance;
			if(r < 0) return item;
		}

		assert(false);
	}

	string id() { return _id; }
	string name() { return _name; }
	ItemGroup base() { return _base; }

	protected {
		Game			_game;
		string			_id, _name;
		ItemGroup		_base = null;

		ItemQuantity[]	_items;
	}

	static void install()
	{
		static ItemGroup current = null;

		Loader!(ItemGroup).add("name",
			(ref ItemGroup group, AST ast, Object[string] state)
			{
				group._id = ast[0].as!string;
				group._name = ast[1].as!string;
				group._game.addItemGroup(group);
			}
		);
		Loader!(ItemGroup).add("base",
			(ref ItemGroup group, AST ast, Object[string] state)
			{
				group._base = group._game.getItemGroup(ast[0].as!string);
			}
		);
		Loader!(ItemGroup).add("item",
			(ref ItemGroup group, AST ast, Object[string] state)
			{
				auto prev = current;
				current = group;

				auto item = new ItemQuantity;
				load(item, ast, state);
				group._items ~= item;

				current = prev;
			}
		);

		Loader!(ItemQuantity).add(0,
			(ref ItemQuantity item, AST ast, Object[string] state)
			{
				item.name = ast.as!string;
			}
		);
		Loader!(ItemQuantity).add("quantity",
			(ref ItemQuantity item, AST ast, Object[string] state)
			{
				item.quantityMin = item.quantityMax = ast[0].as!int;
				if(ast.length >= 2) item.quantityMax = ast[1].as!int;
			}
		);
		Loader!(ItemQuantity).add("depth",
			(ref ItemQuantity item, AST ast, Object[string] state)
			{
				item.depthMin = item.depthMax = ast[0].as!int;
				if(ast.length >= 2) item.depthMax = ast[1].as!int;
			}
		);
		Loader!(ItemQuantity).add("chance",
			(ref ItemQuantity item, AST ast, Object[string] state)
			{
				item.chance = ast[0].as!int;
			}
		);
	}
}
